package me.huha.zhime.service.impl;

import java.text.ParseException;
import java.util.Date;
import java.util.Map;
import java.util.SortedMap;

import me.huha.commons.FormatConstants;
import me.huha.spring.concurrent.AsynsService;
import me.huha.spring.concurrent.Responder;
import me.huha.tools.DateUtils;
import me.huha.zhime.company.client.OutPaymentService;
import me.huha.zhime.company.commons.OutPayment;
import me.huha.zhime.entity.OrderInfoEntity;
import me.huha.zhime.entity.OrderInfoEntity.PaymentStatusEnum;
import me.huha.zhime.entity.WechatAsynchEntity;
import me.huha.zhime.service.OrderService;
import me.huha.zhime.service.WechatPayService;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * @Title: WechatPayServiceImpl
 * @Author: Yepx
 * @mail: yepx2013@gmail.com
 * @CreateTime: 2017年10月25日 下午4:13:35
 * @Todo: TODO
 */
@Service("wechatPayService")
public class WechatPayServiceImpl implements WechatPayService {
	
	private Logger logger = LoggerFactory.getLogger(getClass());
	
	@Autowired
	private OrderService orderService;
	@Autowired
	private OutPaymentService outPaymentService;
	
	@Override
	public Boolean doTradeCallback(SortedMap<Object, Object> callbackMap, Map<String, String> payStatusMap, OrderInfoEntity orderInfo) {
		
		// TODO 保存回调数据
		final String appid = (null != callbackMap.get("appid")) ? callbackMap.get("appid").toString() : null;
		final String mch_id = (null != callbackMap.get("mch_id")) ? callbackMap.get("mch_id").toString() : null;
		final String device_info = (null != callbackMap.get("device_info")) ? callbackMap.get("device_info").toString() : null;
		final String nonce_str = (null != callbackMap.get("nonce_str")) ? callbackMap.get("nonce_str").toString() : null;
		final String sign = (null != callbackMap.get("sign")) ? callbackMap.get("sign").toString() : null;
		final String sign_type = (null != callbackMap.get("sign_type")) ? callbackMap.get("sign_type").toString() : null;
		final String result_code = (null != callbackMap.get("result_code")) ? callbackMap.get("result_code").toString() : null;
		final String err_code = (null != callbackMap.get("err_code")) ? callbackMap.get("err_code").toString() : null;
		final String err_code_des = (null != callbackMap.get("err_code_des")) ? callbackMap.get("err_code_des").toString() : null;
	   	final String openid = (null != callbackMap.get("openid")) ? callbackMap.get("openid").toString() : null;
	   	final String is_subscribe = (null != callbackMap.get("is_subscribe")) ? callbackMap.get("is_subscribe").toString() : null;
	   	final String trade_type = (null != callbackMap.get("trade_type")) ? callbackMap.get("trade_type").toString() : null;
	   	final String bank_type = (null != callbackMap.get("bank_type")) ? callbackMap.get("bank_type").toString() : null;
	   	final String total_fee = (null != callbackMap.get("total_fee")) ? callbackMap.get("total_fee").toString() : null;
	   	final String settlement_total_fee = (null != callbackMap.get("settlement_total_fee")) ? callbackMap.get("settlement_total_fee").toString() : null;
	   	final String fee_type = (null != callbackMap.get("fee_type")) ? callbackMap.get("fee_type").toString() : null;
	   	final String cash_fee = (null != callbackMap.get("cash_fee")) ? callbackMap.get("cash_fee").toString() : null;
	   	final String cash_fee_type = (null != callbackMap.get("cash_fee_type")) ? callbackMap.get("cash_fee_type").toString() : null;
	   	final String coupon_fee = (null != callbackMap.get("coupon_fee")) ? callbackMap.get("coupon_fee").toString() : null;
	   	final String coupon_count = (null != callbackMap.get("coupon_count")) ? callbackMap.get("coupon_count").toString() : null;
	   	final String transaction_id = (null != callbackMap.get("transaction_id")) ? callbackMap.get("transaction_id").toString() : null;
	   	final String out_trade_no = (null != callbackMap.get("out_trade_no")) ? callbackMap.get("out_trade_no").toString() : null;
	   	final String attach = (null != callbackMap.get("attach")) ? callbackMap.get("attach").toString() : null;
	   	final String time_end = (null != callbackMap.get("time_end")) ? callbackMap.get("time_end").toString() : null;
			
		WechatAsynchEntity wechatAsynch = new WechatAsynchEntity(appid, mch_id, device_info, nonce_str, sign, sign_type, 
															result_code, err_code, err_code_des, openid, is_subscribe, 
															trade_type, bank_type, total_fee, settlement_total_fee, 
															fee_type, cash_fee, cash_fee_type, coupon_fee, 
															coupon_count, transaction_id, out_trade_no, attach, time_end);
		
		
		wechatAsynch.createOrUpdate();
		
		//TODO 处理订单业务
		PaymentStatusEnum enum_ = null;
		if("1".equals(payStatusMap.get("payStatus"))){
			enum_ = PaymentStatusEnum.paid;
			
			Date date = null;
			try {
				date = DateUtils.parseDate(time_end, FormatConstants.DATE_TIME_FORMAT_IMAGE_TEMPLATE);
			} catch (ParseException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			final Date date1 = date;
			//异步线程
			AsynsService.asynsService().execute(new Runnable(){

				@Override
				public void run() {
					// TODO Auto-generated method stub
					OutPayment payment = createOutPayment(out_trade_no, transaction_id, true, date1);
					outPaymentService.wechartNotify(payment);
				}
				
			}).addResponder(new Responder() {
				
	            @Override
	            public <T> void onResult(T result) {
	                logger.info("this is result.....");
	            }

	            @Override
	            public void onFault(Exception fault) {
	                logger.error(fault.getMessage(), fault);
	            }
	        });
			
		}else{
			enum_ = PaymentStatusEnum.paidAbnormal;
			OutPayment payment = createOutPayment(out_trade_no, transaction_id, false, null);
			outPaymentService.wechartNotify(payment);
		}
		orderService.updateOrderPaymentStatus(orderInfo.getOrderNum(), enum_);
		
		return true;
	}
	
	 /**
     * 訂單中心需要返回的數據
     * @param paymentSn
     * @param trade_no
     * @param paymentStatus
     * @param paymentDate
     * @return
     */
    private OutPayment createOutPayment(String paymentSn, String trade_no, Boolean paymentStatus, Date paymentDate){
    	
    	OutPayment payment = new OutPayment();
    	payment.setPaymentSn(paymentSn);
    	payment.setTrade_no(trade_no);
    	payment.setPaymentStatus(paymentStatus);
    	payment.setPaymentDate(paymentDate);
    	return payment;
    }
}
